package net.nagaseyasuhito.kinsenka.wicket;

import net.nagaseyasuhito.kinsenka.persist.entity.User;
import net.nagaseyasuhito.kinsenka.service.DebugService;
import net.nagaseyasuhito.kinsenka.wicket.converter.PropertyConverter;
import net.nagaseyasuhito.kinsenka.wicket.page.IndexPage;
import net.nagaseyasuhito.kinsenka.wicket.page.SignInPage;
import net.nagaseyasuhito.kinsenka.wicket.page.SignUpPage;

import org.apache.wicket.ConverterLocator;
import org.apache.wicket.IConverterLocator;
import org.apache.wicket.Page;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.guice.GuiceComponentInjector;
import org.apache.wicket.guice.GuiceInjectorHolder;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;

import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.wideplay.warp.persist.PersistenceService;
import com.wideplay.warp.persist.UnitOfWork;
import com.wideplay.warp.persist.jpa.JpaUnit;

public class KinsenkaApplication extends AuthenticatedWebApplication {

	public static KinsenkaApplication get() {
		return (KinsenkaApplication) WebApplication.get();
	}

	@Override
	public Class<? extends Page> getHomePage() {
		return IndexPage.class;
	}

	/**
	 * {@code Application}が持っている{@code Injector}を返す
	 * 
	 * @return
	 */
	public Injector getInjector() {
		return this.getMetaData(GuiceInjectorHolder.INJECTOR_KEY).getInjector();
	}

	@Override
	protected Class<? extends WebPage> getSignInPageClass() {
		return SignInPage.class;
	}

	@Override
	protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
		return KinsenkaSession.class;
	}

	@Override
	protected void init() {
		super.init();

		this.mountPage("/signIn", SignInPage.class);
		this.mountPage("/signUp", SignUpPage.class);

		// GuiceのJPAモジュールの初期化
		Module persistenceModule = PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).buildModule();
		Module JpaUnitModule = new AbstractModule() {
			@Override
			protected void configure() {
				this.bindConstant().annotatedWith(JpaUnit.class).to("default");
			}
		};

		this.getComponentInstantiationListeners().add(new GuiceComponentInjector(this, persistenceModule, JpaUnitModule));
		this.getRequestCycleListeners().add(new TransactionRequestCycleListener());

		// 開発環境の場合、テストデータを作成
		if (this.usesDevelopmentConfig()) {
			DebugService debugService = this.getInjector().getInstance(DebugService.class);
			debugService.initializeEntity();
		}
	}

	@Override
	protected IConverterLocator newConverterLocator() {
		ConverterLocator converterLocator = new ConverterLocator();
		converterLocator.set(User.class, new PropertyConverter<User>(User.class, "name"));

		return converterLocator;
	}
}
